Added a has_editable field. (_gtk_file_system_model_add_editable): New
authorFederico Mena Quintero <federico@ximian.com>
Sat, 17 Jan 2004 04:34:49 +0000 (04:34 +0000)
committerFederico Mena Quintero <federico@src.gnome.org>
Sat, 17 Jan 2004 04:34:49 +0000 (04:34 +0000)
2004-01-16  Federico Mena Quintero  <federico@ximian.com>

* gtk/gtkfilesystemmodel.c (struct _GtkFileSystemModel): Added a
has_editable field.
(_gtk_file_system_model_add_editable): New function.
(_gtk_file_system_model_remove_editable): New function.
(gtk_file_system_model_get_value): Return appropriate values for
the temporary editable row.
(_gtk_file_system_model_get_info): Handle the editable row.
(_gtk_file_system_model_get_path): Likewise.

* gtk/gtkfilechooserdefault.c (shortcuts_append_bookmarks):
Removed an unused variable.
(toolbar_button_new): Optionally show the button.
(up_button_clicked_cb): Renamed from up_button_cb(), fixed prototype.
(toolbar_create): Add a "New Folder" button for Save mode.
(error_building_filename_dialog): New helper function.
(gtk_file_chooser_default_get_paths): Use error_building_filename_dialog().
(create_file_list): Connect to the "edited" signal of the text
cell renderer.  Store the name column and text renderer in the
impl structure.
(renderer_edited_cb): New callback.
(gtk_file_chooser_default_set_property): Show/hide the "New
folder" button when the save action changes.
(COMPARE_DIRECTORIES): Allow the info values to be NULL.
(COMPARE_DIRECTORIES): Duh, use the list_model, not the
tree_model.
(get_list_file_info): Likewise!
(list_icon_data_func): Handle the path being NULL.
(new_folder_button_clicked): New callback.
(list_name_data_func): If we are on the editable row, set the text
to "Type name of new folder".
(list_selection_changed): Handle the editable row.
(list_mtime_data_func): Likewise.

* gtk/gtkfilesystemunix.c (gtk_file_system_unix_make_path): Return
NULL, not FALSE.
(gtk_file_system_unix_create_folder): Test the result of mkdir() correctly.

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtkfilechooserdefault.c
gtk/gtkfilesystemmodel.c
gtk/gtkfilesystemmodel.h
gtk/gtkfilesystemunix.c

index 8304207af39dddd9f5725fd6b44da88ff325f998..e60c896020fbd323a5dd0f9786f12e2c07d474a9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,42 @@
+2004-01-16  Federico Mena Quintero  <federico@ximian.com>
+
+       * gtk/gtkfilesystemmodel.c (struct _GtkFileSystemModel): Added a
+       has_editable field.
+       (_gtk_file_system_model_add_editable): New function.
+       (_gtk_file_system_model_remove_editable): New function.
+       (gtk_file_system_model_get_value): Return appropriate values for
+       the temporary editable row.
+       (_gtk_file_system_model_get_info): Handle the editable row.
+       (_gtk_file_system_model_get_path): Likewise.
+
+       * gtk/gtkfilechooserdefault.c (shortcuts_append_bookmarks):
+       Removed an unused variable.
+       (toolbar_button_new): Optionally show the button.
+       (up_button_clicked_cb): Renamed from up_button_cb(), fixed prototype.
+       (toolbar_create): Add a "New Folder" button for Save mode.
+       (error_building_filename_dialog): New helper function.
+       (gtk_file_chooser_default_get_paths): Use error_building_filename_dialog().
+       (create_file_list): Connect to the "edited" signal of the text
+       cell renderer.  Store the name column and text renderer in the
+       impl structure.
+       (renderer_edited_cb): New callback.
+       (gtk_file_chooser_default_set_property): Show/hide the "New
+       folder" button when the save action changes.
+       (COMPARE_DIRECTORIES): Allow the info values to be NULL.
+       (COMPARE_DIRECTORIES): Duh, use the list_model, not the
+       tree_model.
+       (get_list_file_info): Likewise!
+       (list_icon_data_func): Handle the path being NULL.
+       (new_folder_button_clicked): New callback.
+       (list_name_data_func): If we are on the editable row, set the text
+       to "Type name of new folder".
+       (list_selection_changed): Handle the editable row.
+       (list_mtime_data_func): Likewise.
+
+       * gtk/gtkfilesystemunix.c (gtk_file_system_unix_make_path): Return
+       NULL, not FALSE.
+       (gtk_file_system_unix_create_folder): Test the result of mkdir() correctly.
+
 Fri Jan 16 23:59:01 2004  Matthias Clasen  <maclas@gmx.de>
 
        The first part of the fix for #114351 (see also 
index 8304207af39dddd9f5725fd6b44da88ff325f998..e60c896020fbd323a5dd0f9786f12e2c07d474a9 100644 (file)
@@ -1,3 +1,42 @@
+2004-01-16  Federico Mena Quintero  <federico@ximian.com>
+
+       * gtk/gtkfilesystemmodel.c (struct _GtkFileSystemModel): Added a
+       has_editable field.
+       (_gtk_file_system_model_add_editable): New function.
+       (_gtk_file_system_model_remove_editable): New function.
+       (gtk_file_system_model_get_value): Return appropriate values for
+       the temporary editable row.
+       (_gtk_file_system_model_get_info): Handle the editable row.
+       (_gtk_file_system_model_get_path): Likewise.
+
+       * gtk/gtkfilechooserdefault.c (shortcuts_append_bookmarks):
+       Removed an unused variable.
+       (toolbar_button_new): Optionally show the button.
+       (up_button_clicked_cb): Renamed from up_button_cb(), fixed prototype.
+       (toolbar_create): Add a "New Folder" button for Save mode.
+       (error_building_filename_dialog): New helper function.
+       (gtk_file_chooser_default_get_paths): Use error_building_filename_dialog().
+       (create_file_list): Connect to the "edited" signal of the text
+       cell renderer.  Store the name column and text renderer in the
+       impl structure.
+       (renderer_edited_cb): New callback.
+       (gtk_file_chooser_default_set_property): Show/hide the "New
+       folder" button when the save action changes.
+       (COMPARE_DIRECTORIES): Allow the info values to be NULL.
+       (COMPARE_DIRECTORIES): Duh, use the list_model, not the
+       tree_model.
+       (get_list_file_info): Likewise!
+       (list_icon_data_func): Handle the path being NULL.
+       (new_folder_button_clicked): New callback.
+       (list_name_data_func): If we are on the editable row, set the text
+       to "Type name of new folder".
+       (list_selection_changed): Handle the editable row.
+       (list_mtime_data_func): Likewise.
+
+       * gtk/gtkfilesystemunix.c (gtk_file_system_unix_make_path): Return
+       NULL, not FALSE.
+       (gtk_file_system_unix_create_folder): Test the result of mkdir() correctly.
+
 Fri Jan 16 23:59:01 2004  Matthias Clasen  <maclas@gmx.de>
 
        The first part of the fix for #114351 (see also 
index 8304207af39dddd9f5725fd6b44da88ff325f998..e60c896020fbd323a5dd0f9786f12e2c07d474a9 100644 (file)
@@ -1,3 +1,42 @@
+2004-01-16  Federico Mena Quintero  <federico@ximian.com>
+
+       * gtk/gtkfilesystemmodel.c (struct _GtkFileSystemModel): Added a
+       has_editable field.
+       (_gtk_file_system_model_add_editable): New function.
+       (_gtk_file_system_model_remove_editable): New function.
+       (gtk_file_system_model_get_value): Return appropriate values for
+       the temporary editable row.
+       (_gtk_file_system_model_get_info): Handle the editable row.
+       (_gtk_file_system_model_get_path): Likewise.
+
+       * gtk/gtkfilechooserdefault.c (shortcuts_append_bookmarks):
+       Removed an unused variable.
+       (toolbar_button_new): Optionally show the button.
+       (up_button_clicked_cb): Renamed from up_button_cb(), fixed prototype.
+       (toolbar_create): Add a "New Folder" button for Save mode.
+       (error_building_filename_dialog): New helper function.
+       (gtk_file_chooser_default_get_paths): Use error_building_filename_dialog().
+       (create_file_list): Connect to the "edited" signal of the text
+       cell renderer.  Store the name column and text renderer in the
+       impl structure.
+       (renderer_edited_cb): New callback.
+       (gtk_file_chooser_default_set_property): Show/hide the "New
+       folder" button when the save action changes.
+       (COMPARE_DIRECTORIES): Allow the info values to be NULL.
+       (COMPARE_DIRECTORIES): Duh, use the list_model, not the
+       tree_model.
+       (get_list_file_info): Likewise!
+       (list_icon_data_func): Handle the path being NULL.
+       (new_folder_button_clicked): New callback.
+       (list_name_data_func): If we are on the editable row, set the text
+       to "Type name of new folder".
+       (list_selection_changed): Handle the editable row.
+       (list_mtime_data_func): Likewise.
+
+       * gtk/gtkfilesystemunix.c (gtk_file_system_unix_make_path): Return
+       NULL, not FALSE.
+       (gtk_file_system_unix_create_folder): Test the result of mkdir() correctly.
+
 Fri Jan 16 23:59:01 2004  Matthias Clasen  <maclas@gmx.de>
 
        The first part of the fix for #114351 (see also 
index 8304207af39dddd9f5725fd6b44da88ff325f998..e60c896020fbd323a5dd0f9786f12e2c07d474a9 100644 (file)
@@ -1,3 +1,42 @@
+2004-01-16  Federico Mena Quintero  <federico@ximian.com>
+
+       * gtk/gtkfilesystemmodel.c (struct _GtkFileSystemModel): Added a
+       has_editable field.
+       (_gtk_file_system_model_add_editable): New function.
+       (_gtk_file_system_model_remove_editable): New function.
+       (gtk_file_system_model_get_value): Return appropriate values for
+       the temporary editable row.
+       (_gtk_file_system_model_get_info): Handle the editable row.
+       (_gtk_file_system_model_get_path): Likewise.
+
+       * gtk/gtkfilechooserdefault.c (shortcuts_append_bookmarks):
+       Removed an unused variable.
+       (toolbar_button_new): Optionally show the button.
+       (up_button_clicked_cb): Renamed from up_button_cb(), fixed prototype.
+       (toolbar_create): Add a "New Folder" button for Save mode.
+       (error_building_filename_dialog): New helper function.
+       (gtk_file_chooser_default_get_paths): Use error_building_filename_dialog().
+       (create_file_list): Connect to the "edited" signal of the text
+       cell renderer.  Store the name column and text renderer in the
+       impl structure.
+       (renderer_edited_cb): New callback.
+       (gtk_file_chooser_default_set_property): Show/hide the "New
+       folder" button when the save action changes.
+       (COMPARE_DIRECTORIES): Allow the info values to be NULL.
+       (COMPARE_DIRECTORIES): Duh, use the list_model, not the
+       tree_model.
+       (get_list_file_info): Likewise!
+       (list_icon_data_func): Handle the path being NULL.
+       (new_folder_button_clicked): New callback.
+       (list_name_data_func): If we are on the editable row, set the text
+       to "Type name of new folder".
+       (list_selection_changed): Handle the editable row.
+       (list_mtime_data_func): Likewise.
+
+       * gtk/gtkfilesystemunix.c (gtk_file_system_unix_make_path): Return
+       NULL, not FALSE.
+       (gtk_file_system_unix_create_folder): Test the result of mkdir() correctly.
+
 Fri Jan 16 23:59:01 2004  Matthias Clasen  <maclas@gmx.de>
 
        The first part of the fix for #114351 (see also 
index 8304207af39dddd9f5725fd6b44da88ff325f998..e60c896020fbd323a5dd0f9786f12e2c07d474a9 100644 (file)
@@ -1,3 +1,42 @@
+2004-01-16  Federico Mena Quintero  <federico@ximian.com>
+
+       * gtk/gtkfilesystemmodel.c (struct _GtkFileSystemModel): Added a
+       has_editable field.
+       (_gtk_file_system_model_add_editable): New function.
+       (_gtk_file_system_model_remove_editable): New function.
+       (gtk_file_system_model_get_value): Return appropriate values for
+       the temporary editable row.
+       (_gtk_file_system_model_get_info): Handle the editable row.
+       (_gtk_file_system_model_get_path): Likewise.
+
+       * gtk/gtkfilechooserdefault.c (shortcuts_append_bookmarks):
+       Removed an unused variable.
+       (toolbar_button_new): Optionally show the button.
+       (up_button_clicked_cb): Renamed from up_button_cb(), fixed prototype.
+       (toolbar_create): Add a "New Folder" button for Save mode.
+       (error_building_filename_dialog): New helper function.
+       (gtk_file_chooser_default_get_paths): Use error_building_filename_dialog().
+       (create_file_list): Connect to the "edited" signal of the text
+       cell renderer.  Store the name column and text renderer in the
+       impl structure.
+       (renderer_edited_cb): New callback.
+       (gtk_file_chooser_default_set_property): Show/hide the "New
+       folder" button when the save action changes.
+       (COMPARE_DIRECTORIES): Allow the info values to be NULL.
+       (COMPARE_DIRECTORIES): Duh, use the list_model, not the
+       tree_model.
+       (get_list_file_info): Likewise!
+       (list_icon_data_func): Handle the path being NULL.
+       (new_folder_button_clicked): New callback.
+       (list_name_data_func): If we are on the editable row, set the text
+       to "Type name of new folder".
+       (list_selection_changed): Handle the editable row.
+       (list_mtime_data_func): Likewise.
+
+       * gtk/gtkfilesystemunix.c (gtk_file_system_unix_make_path): Return
+       NULL, not FALSE.
+       (gtk_file_system_unix_create_folder): Test the result of mkdir() correctly.
+
 Fri Jan 16 23:59:01 2004  Matthias Clasen  <maclas@gmx.de>
 
        The first part of the fix for #114351 (see also 
index 814aafa301b16b630a3342f8938896c182d03a24..d8593feadc1bfaa2c388b3339455acc51d45cdee 100644 (file)
 #include "gtkmessagedialog.h"
 #include "gtkprivate.h"
 #include "gtkscrolledwindow.h"
-#include "gtkseparatortoolitem.h"
 #include "gtksizegroup.h"
 #include "gtkstock.h"
 #include "gtktable.h"
-#include "gtktoolbutton.h"
 #include "gtktreeview.h"
 #include "gtktreemodelsort.h"
 #include "gtktreeselection.h"
@@ -98,6 +96,7 @@ struct _GtkFileChooserDefault
   GtkFilePath *preview_path;
 
   GtkWidget *up_button;
+  GtkWidget *new_folder_button;
 
   GtkWidget *preview_frame;
 
@@ -115,6 +114,9 @@ struct _GtkFileChooserDefault
   GtkWidget *preview_widget;
   GtkWidget *extra_widget;
 
+  GtkTreeViewColumn *list_name_column;
+  GtkCellRenderer *list_name_renderer;
+
   guint folder_mode : 1;
   guint local_only : 1;
   guint preview_widget_active : 1;
@@ -440,6 +442,24 @@ error_could_not_add_bookmark_dialog (GtkFileChooserDefault *impl,
                path, error);
 }
 
+/* Shows an error dialog about not being able to compose a filename */
+static void
+error_building_filename_dialog (GtkFileChooserDefault *impl,
+                               const GtkFilePath     *base_path,
+                               const char            *file_part,
+                               GError                *error)
+{
+  char *msg;
+
+  msg = g_strdup_printf (_("Could not build file name from '%s' and '%s':\n%s"),
+                        gtk_file_path_get_string (base_path),
+                        file_part,
+                        error->message);
+  error_message (impl, msg);
+  g_free (msg);
+  g_error_free (error);
+}
+
 static void
 update_preview_widget_visibility (GtkFileChooserDefault *impl)
 {
@@ -825,8 +845,8 @@ create_shortcuts_model (GtkFileChooserDefault *impl)
 
 /* Callback used when the "Up" toolbar button is clicked */
 static void
-up_button_cb (GtkToolButton         *button,
-             GtkFileChooserDefault *impl)
+up_button_clicked_cb (GtkButton             *button,
+                     GtkFileChooserDefault *impl)
 {
   GtkFilePath *parent_path;
   GError *error;
@@ -847,6 +867,69 @@ up_button_cb (GtkToolButton         *button,
                  error);
 }
 
+/* Callback used when the "New Folder" toolbar button is clicked */
+static void
+new_folder_button_clicked (GtkButton             *button,
+                          GtkFileChooserDefault *impl)
+{
+  GtkTreeIter iter;
+  GtkTreePath *path;
+
+  /* FIXME: this doesn't work for folder mode, just for file mode */
+
+  _gtk_file_system_model_add_editable (impl->list_model, &iter);
+  g_object_set (impl->list_name_renderer, "editable", TRUE, NULL);
+
+  path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->list_model), &iter);
+  gtk_tree_view_set_cursor (GTK_TREE_VIEW (impl->list),
+                           path,
+                           impl->list_name_column,
+                           TRUE);
+}
+
+/* Callback used from the text cell renderer when the new folder is named */
+static void
+renderer_edited_cb (GtkCellRendererText   *cell_renderer_text,
+                   const gchar           *path,
+                   const gchar           *new_text,
+                   GtkFileChooserDefault *impl)
+{
+  GError *error;
+  GtkFilePath *file_path;
+
+  _gtk_file_system_model_remove_editable (impl->list_model);
+  g_object_set (impl->list_name_renderer, "editable", FALSE, NULL);
+
+  error = NULL;
+  file_path = gtk_file_system_make_path (impl->file_system, impl->current_folder, new_text, &error);
+  if (!file_path)
+    {
+      error_building_filename_dialog (impl, impl->current_folder, new_text, error);
+      return;
+    }
+
+  error = NULL;
+  if (!gtk_file_system_create_folder (impl->file_system, file_path, &error))
+    error_dialog (impl,
+                 _("Could not create folder %s:\n%s"),
+                 file_path, error);
+
+  gtk_file_path_free (file_path);
+
+  /* FIXME: scroll to the new folder and select it */
+}
+
+/* Callback used from the text cell renderer when the new folder edition gets
+ * canceled.
+ */
+static void
+renderer_editing_canceled_cb (GtkCellRendererText   *cell_renderer_text,
+                             GtkFileChooserDefault *impl)
+{
+  _gtk_file_system_model_remove_editable (impl->list_model);
+  g_object_set (impl->list_name_renderer, "editable", FALSE, NULL);
+}
+
 /* Creates the widgets for the filter combo box */
 static GtkWidget *
 filter_create (GtkFileChooserDefault *impl)
@@ -863,6 +946,7 @@ toolbar_button_new (GtkFileChooserDefault *impl,
                    const char *text,
                    const char *stock_id,
                    gboolean    sensitive,
+                   gboolean    show,
                    GCallback   callback)
 {
   GtkWidget *button;
@@ -883,6 +967,11 @@ toolbar_button_new (GtkFileChooserDefault *impl,
   gtk_widget_set_sensitive (button, sensitive);
   g_signal_connect (button, "clicked", callback, impl);
 
+  gtk_widget_show_all (hbox);
+
+  if (show)
+    gtk_widget_show (button);
+
   return button;
 }
 
@@ -893,6 +982,7 @@ toolbar_create (GtkFileChooserDefault *impl)
   GtkWidget *hbox;
 
   hbox = gtk_hbox_new (FALSE, 12);
+  gtk_widget_show (hbox);
 
   /* Add bookmark button */
 
@@ -900,6 +990,7 @@ toolbar_create (GtkFileChooserDefault *impl)
                                                  _("Add"),
                                                  GTK_STOCK_ADD,
                                                  FALSE,
+                                                 TRUE,
                                                  G_CALLBACK (add_bookmark_button_clicked_cb));
   gtk_box_pack_start (GTK_BOX (hbox), impl->add_bookmark_button, FALSE, FALSE, 0);
 
@@ -909,6 +1000,7 @@ toolbar_create (GtkFileChooserDefault *impl)
                                                     _("Remove"),
                                                     GTK_STOCK_REMOVE,
                                                     FALSE,
+                                                    TRUE,
                                                     G_CALLBACK (remove_bookmark_button_clicked_cb));
   gtk_box_pack_start (GTK_BOX (hbox), impl->remove_bookmark_button, FALSE, FALSE, 0);
 
@@ -918,7 +1010,8 @@ toolbar_create (GtkFileChooserDefault *impl)
                                        _("Up"),
                                        GTK_STOCK_GO_UP,
                                        FALSE,
-                                       G_CALLBACK (up_button_cb));
+                                       TRUE,
+                                       G_CALLBACK (up_button_clicked_cb));
   gtk_box_pack_start (GTK_BOX (hbox), impl->up_button, FALSE, FALSE, 0);
 
   /* Current folder label */
@@ -926,8 +1019,17 @@ toolbar_create (GtkFileChooserDefault *impl)
   impl->folder_label = gtk_label_new (NULL);
   gtk_misc_set_alignment (GTK_MISC (impl->folder_label), 0.0, 0.5);
   gtk_box_pack_start (GTK_BOX (hbox), impl->folder_label, FALSE, FALSE, 0);
+  gtk_widget_show (impl->folder_label);
 
-  gtk_widget_show_all (hbox);
+  /* New folder button for save mode */
+
+  impl->new_folder_button = gtk_button_new_from_stock (GTK_STOCK_NEW);
+  g_signal_connect (impl->new_folder_button, "clicked",
+                   G_CALLBACK (new_folder_button_clicked), impl);
+  gtk_box_pack_end (GTK_BOX (hbox), impl->new_folder_button, FALSE, FALSE, 0);
+
+  if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+    gtk_widget_show (impl->new_folder_button);
 
   return hbox;
 }
@@ -1339,21 +1441,25 @@ create_file_list (GtkFileChooserDefault *impl)
 
   /* Filename column */
 
-  column = gtk_tree_view_column_new ();
-  gtk_tree_view_column_set_title (column, _("File name"));
-  gtk_tree_view_column_set_sort_column_id (column, FILE_LIST_COL_NAME);
+  impl->list_name_column = gtk_tree_view_column_new ();
+  gtk_tree_view_column_set_title (impl->list_name_column, _("File name"));
+  gtk_tree_view_column_set_sort_column_id (impl->list_name_column, FILE_LIST_COL_NAME);
 
   renderer = gtk_cell_renderer_pixbuf_new ();
-  gtk_tree_view_column_pack_start (column, renderer, TRUE);
-  gtk_tree_view_column_set_cell_data_func (column, renderer,
+  gtk_tree_view_column_pack_start (impl->list_name_column, renderer, TRUE);
+  gtk_tree_view_column_set_cell_data_func (impl->list_name_column, renderer,
                                           list_icon_data_func, impl, NULL);
 
-  renderer = gtk_cell_renderer_text_new ();
-  gtk_tree_view_column_pack_start (column, renderer, TRUE);
-  gtk_tree_view_column_set_cell_data_func (column, renderer,
+  impl->list_name_renderer = gtk_cell_renderer_text_new ();
+  g_signal_connect (impl->list_name_renderer, "edited",
+                   G_CALLBACK (renderer_edited_cb), impl);
+  g_signal_connect (impl->list_name_renderer, "editing-canceled",
+                   G_CALLBACK (renderer_editing_canceled_cb), impl);
+  gtk_tree_view_column_pack_start (impl->list_name_column, impl->list_name_renderer, TRUE);
+  gtk_tree_view_column_set_cell_data_func (impl->list_name_column, impl->list_name_renderer,
                                           list_name_data_func, impl, NULL);
 
-  gtk_tree_view_append_column (GTK_TREE_VIEW (impl->list), column);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (impl->list), impl->list_name_column);
 #if 0
   /* Size column */
 
@@ -1549,6 +1655,11 @@ gtk_file_chooser_default_set_property (GObject      *object,
     {
     case GTK_FILE_CHOOSER_PROP_ACTION:
       impl->action = g_value_get_enum (value);
+      if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+       gtk_widget_show (impl->new_folder_button);
+      else
+       gtk_widget_hide (impl->new_folder_button);
+
       break;
     case GTK_FILE_CHOOSER_PROP_FILE_SYSTEM:
       {
@@ -1785,14 +1896,23 @@ install_list_model_filter (GtkFileChooserDefault *impl)
                                       impl);
 }
 
-#define COMPARE_DIRECTORIES                                                                                    \
-  GtkFileChooserDefault *impl = user_data;                                                                     \
-  const GtkFileInfo *info_a = _gtk_file_system_model_get_info (impl->tree_model, a);                           \
-  const GtkFileInfo *info_b = _gtk_file_system_model_get_info (impl->tree_model, b);                           \
-  gboolean dir_a = gtk_file_info_get_is_folder (info_a);                                                       \
-  gboolean dir_b = gtk_file_info_get_is_folder (info_b);                                                       \
-                                                                                                               \
-  if (dir_a != dir_b)                                                                                          \
+#define COMPARE_DIRECTORIES                                                                                   \
+  GtkFileChooserDefault *impl = user_data;                                                                    \
+  const GtkFileInfo *info_a = _gtk_file_system_model_get_info (impl->list_model, a);                          \
+  const GtkFileInfo *info_b = _gtk_file_system_model_get_info (impl->list_model, b);                          \
+  gboolean dir_a, dir_b;                                                                                      \
+                                                                                                              \
+  if (info_a)                                                                                                 \
+    dir_a = gtk_file_info_get_is_folder (info_a);                                                             \
+  else                                                                                                        \
+    return impl->list_sort_ascending ? -1 : 1;                                                                \
+                                                                                                              \
+  if (info_b)                                                                                                 \
+    dir_b = gtk_file_info_get_is_folder (info_b);                                                             \
+  else                                                                                                        \
+    return impl->list_sort_ascending ? 1 : -1;                                                                \
+                                                                                                              \
+  if (dir_a != dir_b)                                                                                         \
     return impl->list_sort_ascending ? (dir_a ? -1 : 1) : (dir_a ? 1 : -1) /* Directories *always* go first */
 
 /* Sort callback for the filename column */
@@ -2168,14 +2288,7 @@ gtk_file_chooser_default_get_paths (GtkFileChooser *chooser)
 
          if (!selected)
            {
-             char *msg;
-
-             msg = g_strdup_printf (_("Could not build file name from '%s' and '%s':\n%s"),
-                                    gtk_file_path_get_string (folder_path),
-                                    file_part,
-                                    error->message);
-             error_message (impl, msg);
-             g_free (msg);
+             error_building_filename_dialog (impl, folder_path, file_part, error);
              return NULL;
            }
 
@@ -2673,6 +2786,25 @@ static void
 list_selection_changed (GtkTreeSelection      *selection,
                        GtkFileChooserDefault *impl)
 {
+  if (!impl->select_multiple)
+    {
+      GtkTreeSelection *selection;
+      GtkTreeIter iter, child_iter;
+      const GtkFileInfo *info;
+
+      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->list));
+      if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
+       return;
+
+      gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model,
+                                                     &child_iter,
+                                                     &iter);
+
+      info = _gtk_file_system_model_get_info (impl->list_model, &child_iter);
+      if (!info)
+       return; /* We are on the editable row for New Folder */
+    }
+
   update_chooser_entry (impl);
   check_preview_change (impl);
 
@@ -2804,7 +2936,7 @@ get_list_file_info (GtkFileChooserDefault *impl,
                                                  &child_iter,
                                                  iter);
 
-  return _gtk_file_system_model_get_info (impl->tree_model, &child_iter);
+  return _gtk_file_system_model_get_info (impl->list_model, &child_iter);
 }
 
 static void
@@ -2841,6 +2973,8 @@ list_icon_data_func (GtkTreeViewColumn *tree_column,
                                                  &child_iter,
                                                  iter);
   path = _gtk_file_system_model_get_path (impl->list_model, &child_iter);
+  if (!path)
+    return;
 
   /* FIXME: NULL GError */
   pixbuf = gtk_file_system_render_icon (impl->file_system, path, GTK_WIDGET (impl), ICON_SIZE, NULL);
@@ -2890,7 +3024,12 @@ list_name_data_func (GtkTreeViewColumn *tree_column,
   const GtkFileInfo *info = get_list_file_info (impl, iter);
 
   if (!info)
-    return;
+    {
+      g_object_set (cell,
+                   "text", _("Type name of new folder"),
+                   NULL);
+      return;
+    }
 
   set_cell_text_bold_if_folder (info, cell, gtk_file_info_get_display_name (info));
 }
@@ -2905,12 +3044,14 @@ list_size_data_func (GtkTreeViewColumn *tree_column,
 {
   GtkFileChooserDefault *impl = data;
   const GtkFileInfo *info = get_list_file_info (impl, iter);
-  gint64 size = gtk_file_info_get_size (info);
+  gint64 size;
   gchar *str;
 
   if (!info || gtk_file_info_get_is_folder (info))
     return;
 
+  size = gtk_file_info_get_size (info);
+
   if (size < (gint64)1024)
     str = g_strdup_printf (ngettext ("%d byte", "%d bytes", (gint)size), (gint)size);
   else if (size < (gint64)1024*1024)
@@ -2947,7 +3088,12 @@ list_mtime_data_func (GtkTreeViewColumn *tree_column,
 
   info = get_list_file_info (impl, iter);
   if (!info)
-    return;
+    {
+      g_object_set (cell,
+                   "text", "",
+                   NULL);
+      return;
+    }
 
   time_mtime = gtk_file_info_get_modification_time (info);
   g_date_set_time (&mtime, (GTime) time_mtime);
index 66aec6eaf527f4882ecaa782a8ca52e20e65e3e2..e9f6282544b57f979c66a8798455da0e42fc19eb 100644 (file)
@@ -59,6 +59,7 @@ struct _GtkFileSystemModel
   guint show_folders : 1;
   guint show_files : 1;
   guint folders_only : 1;
+  guint has_editable : 1;
 };
 
 struct _FileModelNode
@@ -372,18 +373,31 @@ gtk_file_system_model_get_value (GtkTreeModel *tree_model,
 {
   GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
   FileModelNode *node = iter->user_data;
+  const GtkFileInfo *info;
   
   switch (column)
     {
     case GTK_FILE_SYSTEM_MODEL_INFO:
+      if (model->has_editable && node == model->roots)
+       info = NULL;
+      else
+       info = file_model_node_get_info (model, node);
+
       g_value_init (value, GTK_TYPE_FILE_INFO);
-      g_value_set_boxed (value, file_model_node_get_info (model, node));
+      g_value_set_boxed (value, info);
       break;
     case GTK_FILE_SYSTEM_MODEL_DISPLAY_NAME:
       {
-       const GtkFileInfo *info = file_model_node_get_info (model, node);
        g_value_init (value, G_TYPE_STRING);
-       g_value_set_string (value, gtk_file_info_get_display_name (info));
+
+       if (model->has_editable && node == model->roots)
+         g_value_set_string (value, "");
+       else
+         {
+           const GtkFileInfo *info = file_model_node_get_info (model, node);
+
+           g_value_set_string (value, gtk_file_info_get_display_name (info));
+         }
       }
       break;
     default:
@@ -786,13 +800,22 @@ _gtk_file_system_model_set_show_files (GtkFileSystemModel *model,
  *   is owned by @model and must not be modified or freed.
  *   If you want to save the information for later use,
  *   you must make a copy, since the structure may be
- *   freed on later changes to the file system.
+ *   freed on later changes to the file system.  If you have
+ *   called _gtk_file_system_model_add_editable() and the @iter
+ *   corresponds to the row that this function returned, the
+ *   return value will be NULL.
  **/
 const GtkFileInfo *
 _gtk_file_system_model_get_info (GtkFileSystemModel *model,
                                 GtkTreeIter        *iter)
 {
-  return file_model_node_get_info (model, iter->user_data);
+  FileModelNode *node;
+
+  node = iter->user_data;
+  if (model->has_editable && node == model->roots)
+    return NULL;
+  else
+    return file_model_node_get_info (model, node);
 }
 
 /**
@@ -813,6 +836,9 @@ _gtk_file_system_model_get_path (GtkFileSystemModel *model,
 {
   FileModelNode *node = iter->user_data;
 
+  if (model->has_editable && node == model->roots)
+    return NULL;
+
   if (node->is_dummy)
     return node->parent->path;
   else
@@ -983,6 +1009,71 @@ _gtk_file_system_model_path_do (GtkFileSystemModel       *model,
   return node != NULL;
 }
 
+/**
+ * _gtk_file_system_model_add_editable:
+ * @model: a #GtkFileSystemModel
+ * @iter: Location to return the iter corresponding to the editable row
+ * 
+ * Adds an "empty" row at the beginning of the model.  This does not refer to
+ * any file, but is a temporary placeholder for a file name that the user will
+ * type when a corresponding cell is made editable.  When your code is done
+ * using this temporary row, call _gtk_file_system_model_remove_editable().
+ **/
+void
+_gtk_file_system_model_add_editable (GtkFileSystemModel *model, GtkTreeIter *iter)
+{
+  FileModelNode *node;
+  GtkTreePath *path;
+
+  g_return_if_fail (!model->has_editable);
+
+  model->has_editable = TRUE;
+
+  node = file_model_node_new (model, NULL);
+  node->is_visible = TRUE;
+
+  node->next = model->roots;
+  model->roots = node;
+
+  file_model_node_ref (node);
+
+  path = gtk_tree_path_new ();
+  gtk_tree_path_append_index (path, 0);
+  iter->user_data = node;
+
+  gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, iter);
+
+  gtk_tree_path_free (path);
+}
+
+/**
+ * _gtk_file_system_model_remove_editable:
+ * @model: a #GtkFileSystemModel
+ * 
+ * Removes the "empty" row at the beginning of the model that was
+ * created with _gtk_file_system_model_add_editable().  You should call
+ * this function when your code is finished editing this temporary row.
+ **/
+void
+_gtk_file_system_model_remove_editable (GtkFileSystemModel *model)
+{
+  GtkTreePath *path;
+
+  g_return_if_fail (model->has_editable);
+
+  model->has_editable = FALSE;
+  file_model_node_unref (model, model->roots);
+
+  model->roots = model->roots->next;
+
+  path = gtk_tree_path_new ();
+  gtk_tree_path_append_index (path, 0);
+
+  gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+
+  gtk_tree_path_free (path);
+}
+
 static FileModelNode *
 file_model_node_new (GtkFileSystemModel *model,
                     const GtkFilePath  *path)
index 759c1ab3c1108b322d93fc407923a5a2d8bf2586..890849d5c885b202dca9d6c06b68d01302860a13 100644 (file)
@@ -69,12 +69,16 @@ typedef void (*GtkFileSystemModelPathFunc) (GtkFileSystemModel *model,
                                            GtkTreePath        *path,
                                            GtkTreeIter        *iter,
                                            gpointer            user_data);
-                                  
+
 gboolean _gtk_file_system_model_path_do (GtkFileSystemModel        *model,
                                         const GtkFilePath         *path,
                                         GtkFileSystemModelPathFunc func,
                                         gpointer                   user_data);
 
+void _gtk_file_system_model_add_editable    (GtkFileSystemModel *model,
+                                            GtkTreeIter        *iter);
+void _gtk_file_system_model_remove_editable (GtkFileSystemModel *model);
+
 G_END_DECLS
 
 #endif /* __GTK_FILE_SYSTEM_MODEL_H__ */
index c808b816c0a635ae614a5a771184c8dc19e7e0d5..610c63e0ef0476fd264e510b82c55cd4ba302348 100644 (file)
@@ -324,7 +324,7 @@ gtk_file_system_unix_create_folder (GtkFileSystem     *file_system,
   filename = filename_from_path (path);
   g_return_val_if_fail (filename != NULL, FALSE);
 
-  result = mkdir (filename, 0777) != 0;
+  result = mkdir (filename, 0777) == 0;
 
   if (!result)
     {
@@ -448,7 +448,7 @@ gtk_file_system_unix_make_path (GtkFileSystem    *file_system,
       g_error_free (tmp_error);
       g_free (base_filename);
 
-      return FALSE;
+      return NULL;
     }
 
   full_filename = g_build_filename (base_filename, filename, NULL);